using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using ZedGraph;
using DSP.MathLibrary;
using System.Linq;

namespace DSPVisualization
{
    public partial class OneSignalVisControl : ZedGraphControl
    {
        private TextObj _textField = new TextObj();

        public TextObj TextField
        {
            get { return _textField; }
            set { _textField = value; }
        }

        private GraphPane gpSig = new GraphPane();
        private GraphPane gpSPM = new GraphPane();
        private GraphPane gpTrans = new GraphPane();

        private List<ComplexNumber> _signal;

        public List<ComplexNumber> Signal
        {
            get { return _signal; }
            set { _signal = value; }
        }

        public double TimeStep { get; set; }


        public OneSignalVisControl()
        {
            InitializeComponent();

            this.PointValueEvent += new PointValueHandler(OneSignalVisControl_PointValueEvent);
            this.MasterPane.PaneList.Clear();
            //this.MasterPane.IsFontsScaled = false;

            ZedGraph.GraphPane gpStat = new GraphPane();
            gpStat.Title.Text = "Stat";
            gpStat.Title.FontSpec.Size = 11;
            gpStat.XAxis.Scale.FontSpec.Size = 9;
            gpStat.YAxis.Scale.FontSpec.Size = 9;
            gpStat.IsFontsScaled = false;

            //TextObj text = new TextObj("First Prod\n21-Oct-93\n21-Oct-93\n21-Oct-93\n21-Oct-93", 0.83F, 0.0F);
            // Align the text such that the Bottom-Center is at (175, 80) in user scale coordinates
            this.TextField.Location.X = 0.83;
            this.TextField.Location.Y = 0.02;
            this.TextField.Location.AlignH = AlignH.Left;
            this.TextField.Location.AlignV = AlignV.Top;
            this.TextField.Location.CoordinateFrame = CoordType.PaneFraction;
            //text.FontSpec.Fill = new Fill(Color.White, Color.PowderBlue, 45F);
            this.TextField.FontSpec.StringAlignment = StringAlignment.Near;
            this.MasterPane.GraphObjList.Add(_textField);


            gpSig.Title.Text = "Signal";
            gpSig.Title.FontSpec.Size = 11;
            gpSig.XAxis.Scale.FontSpec.Size = 9;
            gpSig.YAxis.Scale.FontSpec.Size = 9;
            gpSig.IsFontsScaled = false;


            gpTrans.Title.Text = "Transform";
            gpTrans.Title.FontSpec.Size = 11;
            gpTrans.XAxis.Scale.FontSpec.Size = 9;
            gpTrans.YAxis.Scale.FontSpec.Size = 9;
            gpTrans.IsFontsScaled = false;


            gpSPM.Title.Text = "SPM";
            gpSPM.Title.FontSpec.Size = 11;
            gpSPM.XAxis.Scale.FontSpec.Size = 9;
            gpSPM.YAxis.Scale.FontSpec.Size = 9;
            gpSPM.IsFontsScaled = false;

            this.MasterPane.Add(gpSig);
            this.MasterPane.Add(gpTrans);
            this.MasterPane.Add(gpSPM);
            //this.MasterPane.Add(gpStat);

            this.MasterPane.Margin.All = 5;
            this.MasterPane.InnerPaneGap = 5;

            using (Graphics g = this.CreateGraphics())
            {
                this.MasterPane.SetLayout(g, false, new int[] { 3, 1 } , new float[] { 100 });
                this.MasterPane.AxisChange(g);
            }
        }

        string OneSignalVisControl_PointValueEvent(ZedGraphControl sender, GraphPane pane, CurveItem curve, int iPt)
        {
            string txt = "";
            if (pane.Title.Text != "Signal")
            {
                if (iPt != 0)
                {
                    float T = (float)curve.Points.Count * 2.0f / (float)iPt * 1.0f;
                    TimeSpan ts = TimeSpan.FromHours(T);
                    txt = string.Format("n={0} T={1} val={2}", iPt, ts, curve.Points[iPt].Y);
                }
                else
                {
                    txt = string.Format("n={0} T=inf val={1}", iPt,  curve.Points[iPt].Y);
                }
            }
            else
            {
                txt = string.Format("n={0} val={1}", iPt, curve.Points[iPt].Y);
            }
            return txt;
        }

        public void DrawSignal()
        {
            PointPairList sigLst = new PointPairList();
            for (int i = 0; i < Signal.Count; i++)
            {
                sigLst.Add(i, Signal[i].Re);
            }

            LineItem curve = gpSig.AddCurve("lsy", sigLst, Color.Black, SymbolType.None);

            gpSig.XAxis.Scale.Min = 0;
            gpSig.XAxis.Scale.Max = Signal.Count;// / 2;
            this.AxisChange();
        }

        public void DrawFFT()
        {
            List<ComplexNumber> fft = DSP.Library.FourierTransform.CountFastFourierTransform(Signal, false);
            List<ComplexNumber> spm = fft.Select(s => s * ComplexNumber.inv(s) / new ComplexNumber(2.0 * Math.PI, 0)).ToList();

            PointPairList reLst = new PointPairList();
            PointPairList imLst = new PointPairList();
            PointPairList modLst = new PointPairList();
            PointPairList spmLst = new PointPairList();
            double remin = fft.Min(i => i.Re);
            double remax = fft.Max(i => i.Re);
            double immin = fft.Min(i => i.Im);
            double immax = fft.Max(i => i.Im);
            double modmin = fft.Min(i => i.Mod);
            double modmax = fft.Max(i => i.Mod);

            for (int i = 0; i < Signal.Count/2; i++)
            {
               

                reLst.Add(i, fft[i].Re);
                imLst.Add(i, fft[i].Im);
                modLst.Add(i, fft[i].Mod);
                spmLst.Add(i, spm[i].Mod);
            }

            //gpTrans.AddCurve("re", reLst, Color.Blue, SymbolType.None);
            //LineItem imCurve = gpTrans.AddCurve("im", imLst, Color.Red, SymbolType.None);
            //imCurve.IsY2Axis = true;
            //imCurve.YAxisIndex = 1;

            LineItem modCurve = gpTrans.AddCurve("mod", modLst, Color.Green, SymbolType.None);
            //modCurve.IsY2Axis = true;
            //modCurve.YAxisIndex = 1;


            gpSPM.AddCurve("spm", spmLst, Color.Black, SymbolType.None);
           // gpSPM.YAxis.Type = AxisType.Log;
           // gpSPM.XAxis.Type = AxisType.Log;
            gpSPM.XAxis.Scale.Min = 0;
            gpSPM.XAxis.Scale.Max = Signal.Count / 2;


            //gpTrans.YAxis.Type = AxisType.Log;
            gpTrans.YAxis.Scale.Min = modmin;
            gpTrans.YAxis.Scale.Max = modmax;
            //gpTrans.Y2Axis.Scale.Min = immin < modmin ? immin : modmin;
            //gpTrans.Y2Axis.Scale.Max = immax > modmax ? immax : modmax;
            //gpTrans.Y2Axis.IsVisible = true;

           // gpTrans.XAxis.Type = AxisType.Log;
            gpTrans.XAxis.Scale.Min = 0;
            gpTrans.XAxis.Scale.Max = Signal.Count / 2;
            this.AxisChange();
        }
    }
}
